// Copyright 2012 The Plotinum Authors. All rights reserved.
// Use of this source code is governed by an MIT-style license
// that can be found in the LICENSE file.

package plotter

import (
	"code.google.com/p/plotinum/plot"
	"code.google.com/p/plotinum/vg"
	"image/color"
)

var (
	// DefaultGridLineStyle is the default style for grid lines.
	DefaultGridLineStyle = plot.LineStyle{
		Color: color.Gray{128},
		Width: vg.Points(0.25),
	}
)

// Grid implements the plot.Plotter interface, drawing
// a set of grid lines at the (by default) major tick marks.
type Grid struct {
	// Vertical is the style of the vertical lines.
	Vertical plot.LineStyle

	// Horizontal is the style of the horizontal lines.
	Horizontal plot.LineStyle

	// DisplayMinor determines whether to draw minor gridlines or not
	DisplayMinor bool

	// VTickBoundary, if set, draws vertical gridlines corresponding
	// to the tick boundaries, rather than the tick marks themselves,
	// resulting in one more grid line
	VTickBoundary bool
}

// NewGrid returns a new grid with both vertical and
// horizontal lines using the default grid line style.
func NewGrid() *Grid {
	return &Grid{
		Vertical:     DefaultGridLineStyle,
		Horizontal:   DefaultGridLineStyle,
		DisplayMinor: false,
	}
}

// Plot implements the plot.Plotter interface.
func (g *Grid) Plot(da plot.DrawArea, plt *plot.Plot) {
	trX, trY := plt.Transforms(&da)
	hoff := vg.Length(0.0)
	ticks := plt.X.Tick.Marker(plt.X.Min, plt.X.Max)
	if  g.VTickBoundary && len(ticks) > 1{
		hoff = trX((ticks[1].Value-ticks[0].Value)/2) - trX(0) 
	}
	if g.Vertical.Color != nil {
		for _, tk := range ticks {
			if tk.IsMinor() && !g.DisplayMinor {
				continue
			}
			x := trX(tk.Value) - hoff
			da.StrokeLine2(g.Vertical, x, da.Min.Y, x, da.Min.Y+da.Size.Y)
		}
		if hoff > 0 {
			x := da.Max().X + hoff
			da.StrokeLine2(g.Vertical, x, da.Min.Y, x, da.Min.Y+da.Size.Y)
		}
	}

	if g.Horizontal.Color != nil {
		for _, tk := range plt.Y.Tick.Marker(plt.Y.Min, plt.Y.Max) {
			if tk.IsMinor() && !g.DisplayMinor {
				continue
			}
			y := trY(tk.Value)
			da.StrokeLine2(g.Horizontal, da.Min.X-hoff, y, da.Min.X+da.Size.X+hoff, y)
		}
	}
}
